package com.oro.domain;

import static javax.persistence.CascadeType.ALL;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Transient;

import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import static javax.persistence.FetchType.EAGER;

/**
 * Entity implementation class for Entity: Corso
 * 
 */
@Entity
public class Corso extends Servizio implements Serializable {

	private static final long serialVersionUID = 1L;

	@ManyToOne(cascade = ALL)
	@JoinTable(name = "corso_categoria")
	// Uni-directional
	private Categoria categoria;

	private String code;

	private boolean commissionabile;

	private float commissionePercent;

	@OneToMany(mappedBy = "course", cascade = ALL)
	private List<Costo> costi;

	@Transient
	private Costo costToRemove;

	private String description;

	@OneToMany(mappedBy = "corso", cascade = ALL)
	private List<Iscrizione> iscrizioni;

	private String name;

	private String note;

	@ManyToOne(cascade = ALL)
	@JoinTable(name = "corso_scuola")
	private Scuola school;

	@ManyToMany(mappedBy = "corsi", cascade = ALL)
	private List<Sede> sedi;

	@OneToOne(cascade = ALL)
	@JoinTable(name = "corso_materialestudio")
	private MaterialeStudio studyMaterial;

	/**
	 * This is the default commission. This commission is applied to all the
	 * cost, whereas a costo doesn't have it's own commission, which would
	 * override this one.
	 */
	@OneToOne(cascade = ALL)
	@JoinTable(name = "corso_commissioneiscrizione")
	private Commissione subscriptionCommission;

	private float subscriptionFee;

	private String subscriptionFeeCurrency;

	/**
	 * This is the default commission. This commission is applied to all the
	 * cost, whereas a costo doesn't have it's own commission, which would
	 * override this one.
	 */
	@OneToOne(cascade = ALL)
	@JoinTable(name = "corso_commissioneretta")
	private Commissione tuitionCommission;

	public Corso() {
		super();
		sedi = new ArrayList<Sede>();
		costi = new ArrayList<Costo>();
		iscrizioni = new ArrayList<Iscrizione>();
		subscriptionCommission = new Commissione();
		tuitionCommission = new Commissione();
	}

	public Corso(String name) {
		this();
		this.setName(name);
	}

	public Corso(String name, String codice, Categoria categoria) {
		this(name);
		setCode(codice);
		setCategoria(categoria);
	}

	public boolean add(Costo costo) {
		// TODO: add checks
		return costi.add(costo);
	}

	public boolean add(Sede sede) {
		// TODO: add checks
		return sedi.add(sede);
	}

	public boolean addEmptyCost() {
		Costo newCost = new Costo();
		newCost.setCourse(this);
		this.add(newCost);
		return true;
	}

	@Override
	public boolean equals(Object o) {
		if (this == o)
			return true;
		if (o != null)
			if (o instanceof Corso)
				if (getId() != null)
					return this.getId().equals((((Corso) o).getId()));
				else
					return this.getName() == (((Corso) o).getName())
							&& this.getSedi().equals((((Corso) o).getSedi()))
							&& this.getCategoria().equals(
									(((Corso) o).getCategoria()));
			else
				return false;
		else
			return false;
	}

	public Categoria getCategoria() {
		return categoria;
	}

	public String getCode() {
		return code;
	}

	public boolean getCommissionabile() {
		return commissionabile;
	}

	public float getCommissionePercent() {
		return commissionePercent;
	}

	public List<Costo> getCosti() {
		return costi;
	}

	public Costo getCostToRemove() {
		return costToRemove;
	}

	public String getDescription() {
		return description;
	}

	public List<Iscrizione> getIscrizioni() {
		return iscrizioni;
	}

	public String getName() {
		return name;
	}

	public String getNote() {
		return note;
	}

	public Scuola getSchool() {
		return school;
	}

	public List<Sede> getSedi() {
		return sedi;
	}

	public MaterialeStudio getStudyMaterial() {
		return studyMaterial;
	}

	public Commissione getSubscriptionCommission() {
		return subscriptionCommission;
	}

	public float getSubscriptionFee() {
		return subscriptionFee;
	}

	public String getSubscriptionFeeCurrency() {
		return subscriptionFeeCurrency;
	}

	public Commissione getTuitionCommission() {
		return tuitionCommission;
	}

	public float getWeeklyCost(int numWeeks) {
		for (Costo c : getCosti()) {
			if (c.getMinWeeks() == 0 && c.getMaxWeeks() == 0) // By
																// convention,
																// if a Corso
																// has fixed
																// cost, it has
																// only one Cost
																// with both
																// values set to
																// 0.
				return c.getWeeklyPrice();
			if (c.getMinWeeks() <= numWeeks && numWeeks <= c.getMaxWeeks())
				return c.getWeeklyPrice();
		}
		return 0f; // This should never happen, since each Corso has AT LEAST
					// ONE Costo.
	}

	public boolean remove(Costo costToRemove) {
		return costi.remove(costToRemove);
	}

	public boolean removeCost() {
		return getCosti().remove(costToRemove);
	}

	public void setCategoria(Categoria categoria) {
		this.categoria = categoria;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public void setCommissionabile(boolean commissionabile) {
		this.commissionabile = commissionabile;
	}

	public void setCommissionePercent(float commissionePercent) {
		this.commissionePercent = commissionePercent;
	}

	public void setCosti(List<Costo> costi) {
		this.costi = costi;
	}

	public void setCostToRemove(Costo costToRemove) {
		this.costToRemove = costToRemove;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public void setIscrizioni(List<Iscrizione> iscrizioni) {
		this.iscrizioni = iscrizioni;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setNote(String note) {
		this.note = note;
	}

	public void setSchool(Scuola school) {
		this.school = school;
	}

	public void setSedi(List<Sede> sedi) {
		this.sedi = sedi;
	}

	public void setStudyMaterial(MaterialeStudio studyMaterial) {
		this.studyMaterial = studyMaterial;
	}

	public void setSubscriptionCommission(Commissione subscriptionCommission) {
		this.subscriptionCommission = subscriptionCommission;
	}

	public void setSubscriptionFee(float subscriptionFee) {
		this.subscriptionFee = subscriptionFee;
	}

	public void setSubscriptionFeeCurrency(String subscriptionFeeCurrency) {
		this.subscriptionFeeCurrency = subscriptionFeeCurrency;
	}

	public void setTuitionCommission(Commissione tuitionCommission) {
		this.tuitionCommission = tuitionCommission;
	}

}
